import netscape.javascript.JSUtil;
import sun.security.jgss.GSSUtil;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 20404
 * Date: 2023-01-29
 * Time: 1:36
 */
class PrevNum {
    String string;
    int radix;

    public PrevNum() {
    }

    public PrevNum(String string, int radix) {
        this.string = string;
        this.radix = radix;
    }
    public int getValue() {
        return Integer.parseInt(string, radix);
    }

    public void set(String string, int radix) {
        this.string = string;
        this.radix = radix;
    }

    @Override
    public String toString() {
        if(string == null) {
            throw new 你他妈脑子异常("明明没有上一个");
        }
        return "数值为 '" + string + '\'' +
                ", 进制为 " + radix ;
    }
}
public class Test {
    public static ArrayList<String> ReversePN(String expression){

        ArrayList<String> list = new ArrayList<String>();
        Stack<String> stack = new Stack<String>();
        Map<String, Integer> priority = new HashMap<String, Integer>();
        priority.put("+", 1);
        priority.put("-", 1);
        priority.put("*", 2);
        priority.put("/", 2);
        priority.put("^", 2);
        priority.put("%", 2);
        priority.put("(", 0);

        for (int i = 0; i < expression.length(); i++) {
            String read = String.valueOf(expression.charAt(i));
            if (!" ".equals(read)
                    && ("+".equals(read) || "-".equals(read)
                    || "*".equals(read) || "/".equals(read) || "^".equals(read) || "%".equals(read)
                    || "(".equals(read) || ")".equals(read))) {
                if (stack.empty() || read.equals("(")) {
                    stack.push(read);
                } else if (read.equals(")")) {
                    int j = stack.search("(");
                    for (int j2 = 1; j2 < j; j2++) {
                        list.add(stack.pop());
                    }
                    stack.pop();
                } else if (priority.get(read) > priority.get(stack.peek())) {
                    stack.push(read);
                } else {
                    list.add(stack.pop());
                    stack.push(read);
                }

            } else if (!" ".equals(read)) {
                list.add(read);
            }
        }
        for (String string : stack) {
            list.add(string);
        }
        return list;
    }
    public static ArrayList<String> collect(String str) {
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 0; i < str.length(); i++) {
            if(Character.isDigit(str.charAt(i))) {
                StringBuilder stringBuilder = new StringBuilder();
                while (i < str.length() && (Character.isDigit(str.charAt(i)) || str.charAt(i) == '.')) {
                    stringBuilder.append(str.charAt(i));
                    i++;
                }
                arrayList.add(stringBuilder.toString());
            }
        }
        return arrayList;
    }

    public static ArrayList<String> mix(ArrayList<String> arrayList, ArrayList<String> arrayList1) {
        ArrayList<String> retArrayList = new ArrayList<>();
        int ij = 0;
        for (int i = 0; i < arrayList1.size();) {
            StringBuilder stringBuilder = new StringBuilder();
            for (int j = 0; j < arrayList1.get(i).length(); j++) {
                char ch = arrayList.get(ij).charAt(0);
                stringBuilder.append(ch);
                ij++;
                if(!(Character.isDigit(ch) || ch == '.')) {
                    i--;
                    break;
                }
            }
            i++;
            retArrayList.add(stringBuilder.toString());
        }
        for (int i = ij; i < arrayList.size(); i++) {
            retArrayList.add(arrayList.get(i).charAt(0) + "");
        }
        return retArrayList;
    }
    public static void cal(Stack<String> stack, String str) {
        String str1 = stack.pop();
        String str2 = stack.pop();
        Float f1 = Float.parseFloat(str1);
        Float f2 = Float.parseFloat(str2);
        switch (str) {
            case "+":
                stack.push(f1 + f2 + "");
                break;
            case "-":
                stack.push(f2 - f1 + "");
                break;
            case "*":
                stack.push(f1 * f2 + "");
                break;
            case "/":
                if(f1 == 0) {
                    throw new ArithmeticException("计算");
                }
                stack.push(f2 / f1 + "");
                break;
            case "%" :
                if(f1 == 0) {
                    throw new ArithmeticException("计算");
                }
                stack.push(f2 % f1 + "");
                break;
            case "^":
                stack.push(Math.pow(f2, f1) + "");
                break;
        }
    }
    public static String calculate(ArrayList<String> arrayList) {
        Stack<String> stringStack = new Stack<>();
        for (int i = 0; i < arrayList.size(); i++) {
            String str = arrayList.get(i);
            if(str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("^") || str.equals("%")) {
                cal(stringStack, str);
            }else {
                stringStack.push(str);
            }
        }
        return stringStack.pop();
    }
    public static void menu() {
        System.out.println("***********************************");
        System.out.println(" 1. 获取上一次的值继续运算 ");
        System.out.println(" 2. 重新开始计算         ");
        System.out.println(" 3. 进制转化（只限整数）   ");
        System.out.println(" 4. 获取上一次的n进制序列  ");
        System.out.println(" 5. 查看历史记录         ");
        System.out.println(" 0. 退出               ");
        System.out.println("***********************************");
        System.out.print("请选择:> ");
    }
    public static String calCulate(String str) {
        str = str.replaceAll(" ", "");
        ArrayList<String> arrayList1 = collect(str);
        ArrayList<String> arrayList2  = ReversePN(str);
        String s = arrayList2.get(arrayList2.size() - 1);
        if(s.equals("*") || s.equals("/") || s.equals("%") || s.equals("^")) {
            arrayList2.remove(arrayList2.size() - 1);
            int i = arrayList2.size() - 1;
            while(!Character.isDigit(arrayList2.get(i).charAt(0))) {
                i--;
            }
            arrayList2.add(i + 1, s);
        }
        ArrayList<String> arrayList = mix(arrayList2, arrayList1);
        return calculate(arrayList);
    }
    public static void main(String[] args) {
        String str = "";
        Scanner scanner = new Scanner(System.in);
        PrevNum prevNum = new PrevNum();
        ArrayList<String> history = new ArrayList<>();
        int input = 0;
        do {
            menu();
            input = scanner.nextInt();
            scanner.nextLine();
            switch (input) {
                case 1:
                    System.out.println("请在输入 “-” 或者 “/” 或者 “^” 的时候，应将其后面的表达式视为整体用括号括起来以确保先后顺序！");
                    System.out.print("请输入:> " + str);
                    str += scanner.nextLine();
                    String s1 = str;
                    str = calCulate(str);
                    System.out.println("=" + Float.parseFloat(str));
                    history.add(s1 + " = " + Float.parseFloat(str));
                    break;
                case 2:
                    System.out.println("请在输入 “-” 或者 “/” 或者 “^” 的时候，应将其后面的表达式视为整体用括号括起来以确保先后顺序！");
                    System.out.print("请输入:> ");
                    str = scanner.nextLine();
                    String s2 = str;
                    str = calCulate(str);
                    System.out.println("=" + Float.parseFloat(str));
                    history.add(s2 + " = " + Float.parseFloat(str));
                    break;
                case 3:
                    System.out.print("请输入你接下来输入的数的进制:>");
                    int r = scanner.nextInt();
                    scanner.nextLine();
                    System.out.print("请输入整数对应的" + r + "进制数:> ");
                    int number = scanner.nextInt(r);
                    scanner.nextLine();
                    System.out.print("请输入你要转化为进制(2-34):> ");
                    int radix = scanner.nextInt();//括号内输入radix,代表输入什么进制的
                    scanner.nextLine();
                    String string1 = Integer.toString(number, radix);
                    System.out.println("转化成功:> " + string1);
                    history.add(Integer.toString(number, r) + " = " + string1 + " (" + r + "->" + radix + ")");
                    prevNum.set(string1, radix);
                    break;
                case 4 :
                    System.out.println(prevNum);
                    System.out.println("请输入你要转化为进制(2-34):> ");
                    int newRadix = scanner.nextInt();
                    scanner.nextLine();
                    String string2 = Integer.toString(prevNum.getValue(), newRadix);
                    System.out.println("转化成功:> " + string2);
                    history.add(prevNum.string + " = " + string2 + " (" + prevNum.radix + "->" + newRadix + ")");
                    prevNum.set(string2, newRadix);
                    break;
                case 5:
                    System.out.println("========================");
                    if(history.size() == 0) {
                        System.out.println("空");
                    }else {
                        for(String s : history) {
                            System.out.println(s);
                        }
                    }
                    System.out.println("========================");
                    break;
                case 0:
                    System.out.println("退出成功");
                    break;
                default:
                    throw new 你他妈脑子异常(" 艹 ");
            }
        }while(input != 0);
    }
}
